相較於範本驅動表單 (Template-Driven Form) 利用表單樣版讓 Angular 產生對應的表單模型,響應式表單 (Reactive Form) 則是著重在表單模型的定義。這一篇將利用響應式表單 (Ractive Form) 開發待辦事項的表單。
首先,先利用 Angular CLI 新增 TaskForm 元件,將待辦事項表單皆在此元件進行實作,並將其使用在 app.component.html 中。
<app-page-container>
<app-page-title pageTitle="待辦事項清單"></app-page-title>
<div>
<app-task-list></app-task-list>
<app-task-form></app-task-form>
</div>
</app-page-container>
div {
display: flex;
justify-content: space-between;
}
div *:first-child {
margin-right: 10px;
width: 65%;
}
div *:last-child {
width: 35%;
}
另外,也在 app.component.css 加入所需要的樣式,使結果如下圖所示。
在使用響應式表單 (Ractive Form) 開發前,需在 task.module.ts 加入 ReactiveFormsModule
模組。
@NgModule({
imports: [CommonModule, HttpClientModule, FormsModule, ReactiveFormsModule],
declarations: [
TaskComponent,
TaskStateColorDirective,
TaskListComponent,
TaiwanDatePipe,
TaskFormComponent,
],
exports: [TaskComponent, TaskListComponent, TaskFormComponent],
})
export class TaskModule {}
在範本驅動表單 (Template-Driven Form) 中,在使用了 NgForm、NgModelGroup 與 NgModel 指令頁面樣版;Angular 會將 NgForm 與 NgModelGroup 建立為表單群組 (FormGroup) 實體,NgModel 則建立表單控制項 (FormControl) 實體。而在響應式表單 (Ractive Form) 中,則會是宣告與建立 FromGroup 與 FormControl 實體,並利用所對應的指令把表單模型與頁面連結起來。
首先,在 task-form.component.ts 中宣告 FormGroup 屬性,此為整個表單最上層的群組,並將主旨、狀態與等級等資料透過建構式的第一個參數定義為 FormControl 型別。
@Component({
selector: "app-task-form",
templateUrl: "./task-form.component.html",
styleUrls: ["./task-form.component.css"],
})
export class TaskFormComponent implements OnInit {
form: FormGroup;
constructor() {}
ngOnInit(): void {
this.form = new FormGroup({
subject: new FormControl(),
state: new FormControl(0),
level: new FormControl(),
});
}
}
接著,在 task-form.component.html 中定義表單的頁面結構,透過 FormGroup 指令可以將頁面樣版連結至一表單群組;而在此表單群組 (FormGroup) 中,則會利用 FormControlName 與 FormGroupName 指令來連結表單控制項 (FormControl) 或表單群組 (FormGroup)。
<form [formGroup]="form">
<div class="form-field">
<label>主旨</label>
<input type="text" formControlName="subject" />
</div>
<div class="form-field">
<label>等級</label>
<select formControlName="level">
<option value=""></option>
<option value="XS">XS</option>
<option value="S">S</option>
<option value="M">M</option>
<option value="L">L</option>
<option value="XL">XL</option>
</select>
</div>
</form>
<pre>{{ form.value | json }}</pre>
最後,為了讓實作結果能更明顯的效果,在 task-form.component.css 中加入所需的樣式。
form {
padding: 20px;
}
div.form-field {
padding: 10px 20px 10px 0;
margin: 5px 0;
display: flex;
}
div.form-field label {
display: inline-block;
width: 80px;
height: 22px;
line-height: 22px;
text-align: center;
}
div.form-field input,
div.form-field select {
flex-grow: 1;
}
除了利用 new
關鍵字來建立 FormGroup 實體外,Angular 還提供了 FormBuilder 服務元件來建立表單模型;因此,可以在 task-form.component.ts 注入 FormBuilder 服務元件,並利用此服務元件來建立待辦事項表單。
@Component({
selector: "app-task-form",
templateUrl: "./task-form.component.html",
styleUrls: ["./task-form.component.css"],
})
export class TaskFormComponent implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.form = this.fb.group({
subject: this.fb.control(undefined),
state: this.fb.control(0),
level: this.fb.control(undefined),
});
}
}
這一篇利用了響應式表單 (Ractive Form) 定義待辦事項表單,而在待辦事項中還有標籤資訊,且此資訊為一陣列;此時會需要使用到響應式表單 (Ractive Form) 中的表單陣列 (FormArray) 進行定義。